package com.mock.configuration;

import com.mock.contants.HttpContants;
import com.mock.service.impl.NacosRegistryServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * @decription: 全局异常捕获，此mock服务的异常需要特殊处理
 * @author hhk
 * @version 1.0.0
 **/
@Slf4j
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
    

    private RestTemplate restTemplate =new RestTemplate();
    
    /**
     * 捕获到没有匹配的服务时，通过跳转的方式请求真实的服务
     *
     * @param request
     * @return
     */
    @ExceptionHandler({NoHandlerFoundException.class})
    public Object openException(HttpServletRequest request) {
        String method = request.getMethod();
        // 这里暂时先取一台，后续有需要再做迭代
        Map<Integer, List<String>> ipMap = NacosRegistryServiceImpl.getMockRealIpmap();
        // 真实服务的请求url
        String realUrl = HttpContants.PROTOCOL_HTTP + ipMap.entrySet().stream().findAny().get().getValue().get(0) + request.getRequestURI();
        if (HttpContants.GET_METHOD.equalsIgnoreCase(method)) {
            return httpGet(request, realUrl);
        }
        return httpPost(request, realUrl);
    
    }
    
    private ResponseEntity<String> httpPost(HttpServletRequest request, String realUrl) {
        // 转发请求
        try {
            byte[] bytes = IOUtils.toByteArray(request.getInputStream());
            String body = new String(bytes);
            log.info("[请求后置]转发到真实的服务， 真实服务请求url：{},GET请求方法body:{}, remoteHost:{}", realUrl, body, request.getRemoteHost());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> entity = new HttpEntity<>(body, headers);
            ResponseEntity<String> response = restTemplate.exchange(new URI(realUrl), HttpMethod.POST, entity, String.class);
            log.info("response body:{}", response.getBody());
            return response;
        } catch (Exception e) {
            log.error("转发请求异常", e);
        }
        return null;
    }
    
    private ResponseEntity<String> httpGet(HttpServletRequest request, String realUrl) {
        try {
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (MapUtils.isNotEmpty(parameterMap)) {
                // GET请求使用参数拼接的方式处理
                StringBuilder parameterBuilder = new StringBuilder("?");
                for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                    parameterBuilder.append(entry.getKey()).append("=").append(String.join(",", entry.getValue())).append("&");
                }
                // 截掉最后一个&符号，然后拼接到请求路径中
                String params = parameterBuilder.toString();
                realUrl = realUrl + params.substring(0, params.lastIndexOf("&"));
            }
            log.info("[请求后置]转发到真实的服务， 真实服务请求url：{},POST请求body:{}, remoteHost:{}", realUrl, parameterMap, request.getRemoteHost());
            ResponseEntity<String> response = restTemplate.getForEntity(new URI(realUrl).toString(), String.class);
            String body = response.getBody();
            if (StringUtils.isNotBlank(body)) {
                body = new String(body.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                ResponseEntity<String> responseEntity = new ResponseEntity<>(body, response.getHeaders(), response.getStatusCode());
                log.info("response body:{}", body);
                return responseEntity;
            }
            return response;
        } catch (Exception e) {
            log.error("转发请求异常", e);
        }
        return null;
    }
    
    public static void main(String[] args) {
        String[] a = new String[]{"aaaa&ddd&", "ccc"};
        System.out.println(String.join(",", a));
    }
    
}
